package com.cavalier.surtr.redis;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * Created by shiyaobang on 16/4/12.
 */
@Component
public class RedisLock {
    private static final String LOCKED = "LOCKED";
    private static final long ONE_MILLI_NANOS = 1000000L;
    /**
     * 默认超时时间3miao
     */
    private static final int TIME_OUT = 3000;
    private static final int LOCK_TIME_OUT = 30;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    //锁状态标志
    private volatile boolean locked = false;

    private boolean acquireLockWithTimeOut(String key, long timeOut) throws InterruptedException {
        long nano = System.nanoTime();
        timeOut *= ONE_MILLI_NANOS;
        while (System.nanoTime() - nano < timeOut) {
            if (redisTemplate.boundValueOps(key).setIfAbsent(LOCKED)) {
                redisTemplate.expire(key, LOCK_TIME_OUT, TimeUnit.MILLISECONDS);
                locked = true;
                return true;
            }
            Thread.sleep(3, 300);
        }
        return locked;
    }

    public boolean lock(String key) throws InterruptedException {
        return acquireLockWithTimeOut(key, TIME_OUT);
    }

    public boolean lockWithTimeOut(String key, Long timeOut) throws InterruptedException {
        return acquireLockWithTimeOut(key, timeOut);
    }

    public void unlock(String key) {
        if (locked)
            redisTemplate.delete(key);
    }
}
